/**
 * axios 实例
 * @return case 1：code 为 0，成功返回数据 { code, msg, data }
 *         case 2: code 不为 0，在错误捕获中返回 { code, msg, data }
 *         case 3: 请求错误时，在错误捕获中返回 { error } 对象
 * @example const { code, data, msg, error } = await axios
 *            .get(uri, { params })
 *            .catch(error => error)
 * @example axios
 *            .post(uri, { ...params })
 *            .then((data) => { // success })
 *            .catch(({ code, msg, data, error }) => { /error handler })
 * @ref https://github.com/axios/axios
 */

import axios from 'axios'
import { Notify } from 'vant'
import env from './env'

const instance = axios.create({
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  transformRequest: [
    (data) => {
      if (data instanceof FormData || !data) return data

      const query = []
      Object.keys(data).forEach((item) => {
        query.push(`${item}=${encodeURIComponent(data[item])}`)
      })

      return query.join('&')
    },
  ],
  timeout: 10 * 60 * 1000,
})

// 请求拦截
instance.interceptors.request.use((request) => {
  // 设置公共请求 Header 参数
  const token = sessionStorage.getItem('gstoken')
  const { url } = request

  if (url.indexOf('http') === 0) request.baseURL = ''
  else request.baseURL = env.baseURL

  if (token) request.headers.gstoken = token
  return request
})

// 响应拦截
instance.interceptors.response.use(
  ({ config, data: res }) => {
    // res as backend response data
    const { code, msg } = res
    let { showErrorMsg } = config
    if (typeof showErrorMsg !== 'boolean') showErrorMsg = true

    // code === 0 获取数据成功，直接返回 data 数据
    if (code === 0) return res
    if (code === 100201) {
      localStorage.clear()
      sessionStorage.clear()
      // login()
    } else if (showErrorMsg) {
      Notify({ message: msg, type: 'danger' })
    }

    /* eslint prefer-promise-reject-errors: [0, {"allowEmptyReject": true}] */
    return res
  },
  (e) => {
    const error = e ? e.toJSON() : {}
    let { showErrorMsg } = error.config || {}
    if (typeof showErrorMsg !== 'boolean') showErrorMsg = true
    if (showErrorMsg) Notify({ message: error.message, type: 'danger' })
    return Promise.resolve(error)
  },
)

export default instance
